import { BaseEnvMirror } from "@/modules/dev-env/mirror/mirror.ts";
import type { ToolInstallVersionItem } from "@/modules/dev-env/common/types.ts";
import type { NpmMirrorFileItem } from "@/modules/dev-env/common/npmmirror-types.ts";
import { getPlatform } from "@/util/system-utils2.ts";
import path from "@/framework/util/path.ts";
import semver from "semver";
import { MirrorDataFilter } from "@/modules/dev-env/mirror/filter.ts";

/**
 * nodejs版本过滤器
 */
class NodejsVersionFilter extends MirrorDataFilter<string> {
  constructor() {
    super("版本");
  }

  setVersions(versions: number[]) {
    versions.sort((a, b) => b - a);
    this.setDataSource(versions.map(it => ({ value: it.toString() })));
    this.value = versions[0].toString();
    this.events.emit("data-source-change");
  }

  protected filter0(versions: ToolInstallVersionItem[]): ToolInstallVersionItem[] {
    return versions.filter(it => it.edition === this.value);
  }
}

/**
 * npmmirror.com nodejs下载源
 */
export class NodejsNpmMirror extends BaseEnvMirror {
  private readonly versionFilter = new NodejsVersionFilter();

  constructor() {
    super({
      id: "nodejs.npmmirror",
      name: "NpmMirror",
      url: "https://registry.npmmirror.com/-/binary/node/",
      website: "https://npmmmirror.com/",
    });
  }

  protected getFilters0(): MirrorDataFilter[] {
    return [this.versionFilter];
  }

  async getDownloadList(query: Record<string, any>): Promise<ToolInstallVersionItem[]> {
    const resp = await native.http.getJson<NpmMirrorFileItem[]>(this.url);
    const items: ToolInstallVersionItem[] = [];
    const versionSet = new Set<number>();
    for (const it of resp.data) {
      if (it.type === "dir" && it.name?.startsWith("v")) {
        const version = it.name.replace("v", "").replace("/", "");
        const downloadUrl = getNodeDownloadUrl(this.url, version);
        const name = path.basename(downloadUrl);
        const [major] = version.split(".");
        items.push({
          id: `node-${version}`,
          name: name,
          version: version,
          url: downloadUrl,
          date: new Date(it.modified).toLocaleString(),
          edition: major,
        });
        versionSet.add(+major);
      }
    }

    items.sort((a, b) => semver.compare(b.version, a.version));

    this.versionFilter.setVersions([...versionSet]);
    return items;
  }
}

function getNodeDownloadUrl(url: string, version: string) {
  // https://registry.npmmirror.com/-/binary/node/v20.9.0/node-v20.9.0-win-x86.7z
  return `${url}v${version}/node-v${version}-${getPlatform()}-${native.process.arch}.7z`;
}
